﻿/**
 * @file shell_port.c
 * @author Letter (NevermindZZT@gmail.com)
 * @brief 
 * @version 0.1
 * @date 2019-02-22
 * 
 * @copyright (c) 2019 Letter
 * 
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "log.h"
#include "lwrb.h"
#include "xtime_l.h"

// shell读取数据的buffer,串口负责写入数据
lwrb_t ShellReadBufferHandle_;
char ShellReadBufferData_[1024];
// shell写入数据的buffer,串口负责读取数据
lwrb_t ShellWriteBufferHandle_;
char ShellWriteBufferData_[1024];

Shell shell;
char shellBuffer[4096];
// char shellPathBuffer[512] = "/";
Log log = {.active = 1, .level = LOG_DEBUG};


lwrb_t *ShellReadBufferHandle() {
  return &ShellReadBufferHandle_;
}

lwrb_t *ShellWriteBufferHandle() {
  return &ShellWriteBufferHandle_;
}

/**
 * @brief 获取系统tick
 */
unsigned int curTime() {
  XTime curTime;
  XTime_GetTime(&curTime);
  return curTime * 1000.0 / COUNTS_PER_SECOND;
}

/**
 * @brief 日志写函数实现
 *
 * @param buffer 数据
 * @param len 数据长度
 *
 */
void terminalLogWrite(char *buffer, short len) {
  if (log.shell) {
    shellWriteEndLine(log.shell, buffer, len);
  }
}

/**
 * @brief 用户shell写入到串口,需要让串口打印到界面
 * @param data 数据
 * @param len 数据长度
 */
unsigned short userShellWrite(char *data, unsigned short len) {
  return lwrb_write(&ShellWriteBufferHandle_, data, len);
}

/**
 * @brief 用户shell读,串口从界面进行输入的数据
 * @param data 数据
 * @param len 数据长度
 */
unsigned short userShellRead(char *data, unsigned short len) {
  return lwrb_read(&ShellReadBufferHandle_, data, len);
}

#if SHELL_USING_LOCK == 1
static int lockCount = 0;
int userShellLock(struct shell_def *shell) {
  printf("lock: %d\r\n", lockCount);
  return 0;
}

int userShellUnlock(struct shell_def *shell) {
  printf("unlock: %d\r\n", lockCount);
  return 0;
}
#endif

/**
 * @brief 用户shell初始化
 *
 */
void userShellInit() {
  // 初始化读写缓存
  lwrb_init(&ShellReadBufferHandle_, ShellReadBufferData_,
            sizeof ShellReadBufferData_);
  lwrb_reset(&ShellReadBufferHandle_);
  lwrb_init(&ShellWriteBufferHandle_, ShellWriteBufferData_,
            sizeof ShellWriteBufferData_);
  lwrb_reset(&ShellWriteBufferHandle_);

  shell.write = userShellWrite;
  shell.read = userShellRead;
  // shellSetPath(&shell, shellPathBuffer);
  shellInit(&shell, shellBuffer, sizeof(shellBuffer));

  log.write = terminalLogWrite;
  logRegister(&log, &shell);

  // logHexDump(LOG_ALL_OBJ, LOG_DEBUG, (void *)&shell, sizeof(shell));
}

int myTest(int val0, int val1) {
  auto r = val0 * val1;
  logInfo("hello my shell: %d", r);
  return r;
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
                 test, myTest, test function detail);

/*
int varInt = 0;
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_INT),
                 varInt, &varInt, int var test);

char str[] = "test string";
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_STRING),
                 varStr, str, string var test);

SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_POINT),
                 shell, &shell, pointer var test);

int dumpInfo(void) {
  printf("hello world\r\n");
  return 0;
}

int sysInfoSet(int value) {
  printf("sys info: %d\r\n", value);
  return value;
}

ShellNodeVarAttr sysInfo = {
    .get = dumpInfo,
    .set = sysInfoSet,
};
SHELL_EXPORT_VAR(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_NODE),
                 sysInfo, &sysInfo, node var test);

int shellInfoGet(Shell *shell) {
  printf("user name: %s\r\n", shell->info.user->data.user.name);
  printf("path: %s\r\n", shell->info.path);
  return (int) shell;
}

ShellNodeVarAttr shellInfo = {
    .var = &shell,
    .get = shellInfoGet,
};
SHELL_EXPORT_VAR(
    SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_VAR_NODE)|
    SHELL_CMD_READ_ONLY,
    shellInfo, &shellInfo, node var test);

void shellKeyTest(void) {
  char data;
  Shell *shell = shellGetCurrent();
  SHELL_ASSERT(shell && shell->read, return);
  while (1) {
    if (shell->read(&data, 1) == 1) {
      if (data == '\n' || data == '\r') {
        return;
      }
      shellPrint(shell, "%02x ", data);
    }
  }
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
                 keyTest, shellKeyTest, key test);

void shellScanTest(void) {
  int a;
  char b[12];
  shellScan(shellGetCurrent(), "%x %s\n", &a, b);
  shellPrint(shellGetCurrent(), "result: a = %x, b = %s\r\n", a, b);
}

SHELL_EXPORT_CMD(
    SHELL_CMD_PERMISSION(0x00)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|
    SHELL_CMD_DISABLE_RETURN,
    scanTest, shellScanTest, test scan);


void shellPassthroughTest(char *data, unsigned short len) {
  printf("passthrough mode test, data: %s, len: %d\r\n", data, len);
}

int shellRetValChange(int value) {
  return value;
}

SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC),
                 changeRetVal, shellRetValChange, change shell return vallue);
*/